//
//  YDBTManager.m
//  IngCard
//
//  Created by kf on 2017/7/13.
//  Copyright © 2017年 IngDan. All rights reserved.
//

#import "YDBTMessageManager.h"
#import "BabyBluetooth.h"
#import "YDBTMessage.h"


@interface YDBTMessageManager()
@property(nonatomic, strong) BabyBluetooth *bt;
@property(nonatomic, strong) CBPeripheral *currentPeripheral;
@property(nonatomic, strong) CBCharacteristic *writeChar;
@property(nonatomic, strong) CBCharacteristic *readChar;

@property(nonatomic) YDBTMessageStatus btStatus;

//串行的增删，并行的改查
@property (nonatomic, strong, nullable) dispatch_queue_t messageQueue;
@property(nonatomic, strong) NSMutableArray<YDBTMessage *> *messages;
@property(nonatomic, strong) YDBTMessage *currentMessage;
@end

@implementation YDBTMessageManager
//@synthesize btStatus;

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static YDBTMessageManager *instance = nil;
    dispatch_once(&onceToken,^{
        instance = [[super allocWithZone:NULL] init];
        
    });
    return instance;
}

+ (id)allocWithZone:(struct _NSZone *)zone{
    return [self sharedInstance];
}



#pragma mark - public

- (void) run
{
    [self writeWithComplete:^(BOOL success) {
        
    }];
    
    
    [self initBTDelegate];

    [self.bt stop];
//    [self.bt enjoy];
    self.bt.scanForPeripherals().begin().stop(10);
}


-(void) checkStatusWithComplete:(void (^)(BOOL success))onComplete
{
    NSData *data = [self hexToBytes:@"A55A0100000000000B000D"];
    
    YDBTMessage *message = [[YDBTMessage alloc] init];
    message.content = data;
    message.complete = onComplete;
    
//    dispatch_barrier_async(self.messageQueue, ^{
        [self.messages addObject:message];
        [self performanceMessage];
//    });
}

-(void) readWithComplete:(void (^)(BOOL success))onComplete
{
    NSData *data = [self hexToBytes:@"A55A03000301FE0D"];
    
    YDBTMessage *message = [[YDBTMessage alloc] init];
    message.content = data;
    message.complete = onComplete;
    
//    dispatch_barrier_async(self.messageQueue, ^{
        [self.messages addObject:message];
        [self performanceMessage];
//    });
}

-(void) writeWithComplete:(void (^)(BOOL success))onComplete
{
    
//    10+ length
    
    
    NSString *head = @"A55A030201010A";//03F2";   8位;; 16进制ASCll码
    NSString *content = @"1;'[o";
    NSString *length = [NSString qmui_hexStringWithInteger:(content.length + 10)]; // 16进制ASCLL码
    NSString *tail = @"0D"; //1位;; 16进制ASCll码
    
    while (length.length < 4) {
        length = NSStringFormat(@"0%@",length);
    }
    
    NSData * temp = [content dataUsingEncoding:(NSASCIIStringEncoding)];
    
    NSString *tempString = [[NSString alloc] initWithData:temp  encoding:NSUTF8StringEncoding];
    
    NSString *result = NSStringFormat(@"%@%@%@%@",head,length,content,tail);
    
    NSData *data = [self hexToBytes:result];

    YDBTMessage *message = [[YDBTMessage alloc] init];
    message.content = data;
    message.complete = onComplete;
    
//    dispatch_barrier_async(self.messageQueue, ^{
        [self.messages addObject:message];
        [self performanceMessage];
//    });
}

#pragma mark - Private

- (void) initBTDelegate
{
    Weak(self)
    [self.bt setBlockOnCentralManagerDidUpdateState:^(CBCentralManager *central) {
        //todo 增加提示
        Strong(self);
        if (central.state != CBCentralManagerStatePoweredOn)
        {
            
        }
        else if (central.state == CBCentralManagerStatePoweredOn)
        {
            [self.bt stop];
            self.bt.scanForPeripherals().begin().stop(10);
        }
    }];
    
    [self.bt setBlockOnDiscoverToPeripherals:^(CBCentralManager *central,
                                                 CBPeripheral *peripheral,
                                                 NSDictionary *advertisementData,
                                                 NSNumber *RSSI) {
        Strong(self);
        
        
        self.bt.having(peripheral).and.connectToPeripherals().discoverServices().discoverCharacteristics().
        readValueForCharacteristic().
        discoverDescriptorsForCharacteristic().
        readValueForDescriptors().begin();
        
        [self.bt cancelScan];
    }];
    
    //设置查找设备的过滤器
    [self.bt setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        if ([peripheralName hasPrefix:@"MT"] >0) {
            return YES;
        }
        return NO;
    }];
    
    
    [self.bt setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
        Strong(self);
        self.currentPeripheral = peripheral;
        [self.bt AutoReconnect:peripheral];
    }];
    
    [self.bt setBlockOnDiscoverDescriptorsForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        Log(@"Descriptors : %@, %@",characteristic.UUID.UUIDString, characteristic.value);
        
        Strong(self);
        if([characteristic.UUID.UUIDString isEqualToString:@"F1F1"])
        {
            self.writeChar = characteristic;
            
            [self checkStatusWithComplete:^(BOOL success) {
                
            }];
            Log(@"ReadValue : %@ , %@",characteristic.UUID.UUIDString,characteristic.value);
        }
    }];
    
    [self.bt setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        
        Strong(self);
        
        if(![characteristic isNotifying])
        {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
        
        if([characteristic.UUID.UUIDString isEqualToString:@"F1F2"])
        {
            Log(@"ReadValue : %@ , %@",characteristic.UUID.UUIDString,characteristic.value);
        }
    }];
}

- (void) performanceMessage
{
//    if (self.btStatus == BTIdle)
//    {
        if (self.currentMessage && [self.messages containsObject:self.currentMessage])
        {
            [self.messages removeObject:self.currentMessage];
        }

        if (self.messages.count <= 0 || !self.currentPeripheral ) return;

        self.currentMessage = [self.messages objectAtIndex:0];
        
        self.btStatus = BTWriting;
    
    
    Log(@"Message = %@",self.currentMessage.content);
        [self.currentPeripheral writeValue:self.currentMessage.content
                         forCharacteristic:self.writeChar
                                      type:CBCharacteristicWriteWithResponse];
    
}

- (NSData *)hexToBytes:(NSString *)str
{
    NSMutableData* data = [NSMutableData data];
    int idx;
    for (idx = 0; idx+2 <= str.length; idx+=2) {
        NSRange range = NSMakeRange(idx, 2);
        NSString* hexStr = [str substringWithRange:range];
        NSScanner* scanner = [NSScanner scannerWithString:hexStr];
        unsigned int intValue;
        [scanner scanHexInt:&intValue];
        [data appendBytes:&intValue length:1];
    }
    return data;
}


//- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
//{
//    if ([keyPath isEqualToString:@"messages"])
//    {
//
//    }
//}

#pragma mark - lazy Loading

- (BabyBluetooth *)bt
{
    if (!_bt)
    {
        _bt = [BabyBluetooth shareBabyBluetooth];
        NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
        [_bt setBabyOptionsWithScanForPeripheralsWithOptions:scanForPeripheralsWithOptions
                                  connectPeripheralWithOptions:nil
                                scanForPeripheralsWithServices:nil
                                          discoverWithServices:nil
                                   discoverWithCharacteristics:nil];
    }
    return _bt;
}

-(void) setBtStatus:(YDBTMessageStatus)btStatus
{
    if (btStatus != _btStatus)
    {
        _btStatus = btStatus;
        
//        [self performanceMessage];
    }
}

-(NSMutableArray<YDBTMessage *> *)messages
{
    if (!_messages)
    {
        _messages = [NSMutableArray array];
    }
    return _messages;
}
-(dispatch_queue_t) messageQueue
{
    if (!_messages)
    {
        _messageQueue = dispatch_queue_create("YD.Concurrent.MessageQueue", DISPATCH_QUEUE_CONCURRENT);
    }
    return _messageQueue;
}
@end
